package com.ttc.mBackupK16.BackupContacts;

import java.io.InputStream;
import java.util.ArrayList;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;

public class ContactsManager {

	private Cursor cur;
	private ContentResolver cr;

	public Cursor getCur() {
		return cur;
	}

	public void setCur(Cursor cur) {
		this.cur = cur;
	}

	public ContentResolver getCr() {
		return cr;
	}

	public void setCr(ContentResolver cr) {
		this.cr = cr;
	}

	// Get Contact List
	public ContactList getContactList() {
		ContactList contacts = new ContactList();
		String id;
		this.cur = this.cr.query(ContactsContract.Contacts.CONTENT_URI, null,
				null, null, null);
		if (this.cur.getCount() > 0) {
			while (cur.moveToNext()) {
				Contact c = new Contact();
				id = cur.getString(cur
						.getColumnIndex(ContactsContract.Contacts._ID));
				c.setId(id);
				c.setDisplayName(cur.getString(cur
						.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
				c.setStructuredName(this.getStructuredName(id));
				c.setPhoto(this.getContactPhoto(id));
				if (Integer
						.parseInt(cur.getString(cur
								.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
					c.setPhone(this.getPhoneNumbers(id));
				}
				c.setEmail(this.getEmailAddresses(id));
				c.setNotes(this.getContactNotes(id));
				c.setAddresses(this.getContactAddresses(id));
				c.setImAddresses(this.getIM(id));
				c.setOrganization(this.getContactOrg(id));
				contacts.addContact(c);
			}
		}
		return (contacts);
	}

	private MyStructuredName getStructuredName(String id){
		MyStructuredName structuredName=new MyStructuredName();
		String where=ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID +"=?";
		String[] args=new String[]{id};
		Cursor mCursor = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, args, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
		while(mCursor.moveToNext()){
			String display=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
			String family=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
			String given=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
			String middle=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
			String phoneticFamily=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME));
			String phoneticGiven=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME));
			String phoneticMiddle=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME));
			String prefix=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX));
			String suffix=mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX));
			
			structuredName.setDisplayName(display);
			structuredName.setFamilyName(family);
			structuredName.setGivenName(given);
			structuredName.setMiddleName(middle);
			structuredName.setNamePrefix(prefix);
			structuredName.setNameSuffix(suffix);
			structuredName.setPhoneticFamilyName(phoneticFamily);
			structuredName.setPhoneticGivenName(phoneticGiven);
			structuredName.setPhoneticMiddleName(phoneticMiddle);
		}
		return structuredName;
	}
	
	public Bitmap getContactPhoto(String id){
		Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
		InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
		return BitmapFactory.decodeStream(input);
		//return input;
	}
	
	public ArrayList<Phone> getPhoneNumbers(String id) {
		ArrayList<Phone> phones = new ArrayList<Phone>();

		Cursor pCur = this.cr.query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
				ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
				new String[] { id }, null);
		while (pCur.moveToNext()) {
			phones.add(new Phone(
					pCur.getString(pCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)),
					pCur.getString(pCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));

		}
		pCur.close();
		return (phones);
	}

	public ArrayList<Email> getEmailAddresses(String id) {
		ArrayList<Email> emails = new ArrayList<Email>();

		Cursor emailCur = this.cr.query(
				ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
				ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
				new String[] { id }, null);
		while (emailCur.moveToNext()) {
			// This would allow you get several email addresses
			Email e = new Email(
					emailCur.getString(emailCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)),
					emailCur.getString(emailCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE)));
			emails.add(e);
		}
		emailCur.close();
		return (emails);
	}

	public ArrayList<String> getContactNotes(String id) {
		ArrayList<String> notes = new ArrayList<String>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND "
				+ ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id,
				ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE };
		Cursor noteCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null,
				where, whereParameters, null);
		while (noteCur.moveToNext()) {
			String note = noteCur
					.getString(noteCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
			if (note.length() > 0) {
				notes.add(note);
			}
		}
		noteCur.close();
		return (notes);
	}

	public ArrayList<Address> getContactAddresses(String id) {
		ArrayList<Address> addrList = new ArrayList<Address>();

		String where = ContactsContract.Data.CONTACT_ID + " = ? AND "
				+ ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] {
				id,
				ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE };

		Cursor addrCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null,
				where, whereParameters, null);
		while (addrCur.moveToNext()) {
			String poBox = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
			String street = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
			String city = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
			String state = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
			String postalCode = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
			String country = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
			String type = addrCur
					.getString(addrCur
							.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));
			Address a = new Address(poBox, street, city, state, postalCode,
					country, type);
			addrList.add(a);
		}
		addrCur.close();
		return (addrList);
	}

	public ArrayList<IM> getIM(String id) {
		ArrayList<IM> imList = new ArrayList<IM>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND "
				+ ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id,
				ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE };

		Cursor imCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null,
				where, whereParameters, null);
		while (imCur.moveToNext()) {
			String imName = imCur.getString(imCur
					.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA));
			String imType;
			imType = imCur
					.getString(imCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL));
			if (imName.length() > 0) {
				IM im = new IM(imName, imType);
				imList.add(im);
			}
		}
		imCur.close();
		return (imList);
	}

	public ArrayList<Organization> getContactOrg(String id) {
		ArrayList<Organization> orgs = new ArrayList<Organization>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND "
				+ ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id,
				ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE };

		Cursor orgCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null,
				where, whereParameters, null);

		while (orgCur.moveToNext()) {
			String orgName = orgCur
					.getString(orgCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
			String title = orgCur
					.getString(orgCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
			String type = orgCur
					.getString(orgCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE));
			if (orgName.length() > 0) {
				Organization org = new Organization(orgName, title, type);
				orgs.add(org);
			}
		}
		orgCur.close();
		return (orgs);
	}

	public boolean WriteSingleContact(Contact contact) {
		try{
			// DELETE CONTACT
			Uri personUri = ContactsContract.RawContacts.CONTENT_URI;
			String where = ContactsContract.Contacts.DISPLAY_NAME + "=?";
			cr.delete(personUri, where, new String[] { contact.getDisplayName()});
			Log.v("Displayname", contact.getDisplayName());
			ContentValues values = new ContentValues();
			values.put(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
					contact.getDisplayName());
			Uri rawContactUri = cr.insert(RawContacts.CONTENT_URI, values);
			long rawContactId = ContentUris.parseId(rawContactUri);
	
			values.clear();
			values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
			values.put(ContactsContract.Data.MIMETYPE,
					StructuredName.CONTENT_ITEM_TYPE);
			values.put(StructuredName.DISPLAY_NAME, contact.getStructuredName().getDisplayName());
			cr.insert(ContactsContract.Data.CONTENT_URI, values);
			
			Uri phoneUri = null;
			Uri emailUri = null;
			Uri addressUri = null;
			Uri imUri = null;
			Uri orgUri = null;
			Uri noteUri = null;
			Uri strnameUri = null;
			Uri photoUri = null;
			if(contact.getPhoto() != null){
				photoUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
			}
			if(contact.getStructuredName()!=null){
				Log.i("DisplayName", "" + contact.getStructuredName().getDisplayName());
				strnameUri=Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getStructuredName().getDisplayName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, contact.getStructuredName().getFamilyName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, contact.getStructuredName().getGivenName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, contact.getStructuredName().getMiddleName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME, contact.getStructuredName().getPhoneticFamilyName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME, contact.getStructuredName().getPhoneticMiddleName());
				values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME, contact.getStructuredName().getPhoneticGivenName());
				this.cr.insert(strnameUri, values);
			}
			for (Phone aPhone : contact.getPhone()) {
	
				phoneUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Phone.TYPE,
						aPhone.getType());
				values.put(ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY,
						1);
				values.put(ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,
						aPhone.getNumber());
				cr.insert(phoneUri, values);
			}
			for (Email aEmail : contact.getEmail()) {
				emailUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
	
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Email.TYPE,
						aEmail.getType());
				values.put(ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Email.DATA,
						aEmail.getAddress());
				cr.insert(emailUri, values);
			}
			for (String aNote : contact.getNotes()) {
				noteUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Note.NOTE, aNote);
				cr.insert(noteUri, values);
			}
			for (IM aIM : contact.getImAddresses()) {
				imUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
						aIM.getType());
				values.put(ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Im.DATA, aIM.getName());
				cr.insert(imUri, values);
			}
			for (Organization aORG : contact.getOrganization()) {
				orgUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Organization.TYPE,
						aORG.getType());
				values.put(ContactsContract.CommonDataKinds.Organization.TITLE,
						aORG.getTitle());
				values.put(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Organization.DATA,
						aORG.getOrganization());
				cr.insert(orgUri, values);
			}
			for (Address aAdd : contact.getAddresses()) {
				addressUri = Uri.withAppendedPath(rawContactUri,
						ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
				if (aAdd.getCity() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.CITY,
							aAdd.getCity());
				if (aAdd.getCountry() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,
							aAdd.getCountry());
				if (aAdd.getPoBox() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.POBOX,
							aAdd.getPoBox());
				if (aAdd.getPostalCode() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE,
							aAdd.getPostalCode());
				if (aAdd.getStreet() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.STREET,
							aAdd.getStreet());
				if (aAdd.getState() != null)
					values.put(
							ContactsContract.CommonDataKinds.StructuredPostal.REGION,
							aAdd.getState());
				values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
						aAdd.getType());
				cr.insert(addressUri, values);
			}
			
			return true;
		}catch (Exception e) {
			// TODO: handle exception
			return false;
		}
	}

	public boolean WriteContact(ArrayList<Contact> LstContact) {
		try {
			for (Contact contact : LstContact) {
				WriteSingleContact(contact);
			}
			return true;
		} catch (Exception ex) {
			Log.d("ERROR", ex.toString());
			return false;
		}
	}
}
